import sys
import os

# 添加父目录到sys.path
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

import streamlit as st
import pandas as pd
import plotly.graph_objects as go
from db import DataBase
from utils.enums import DeviceName, PastTime
import datetime
from streamlit_autorefresh import st_autorefresh

st_autorefresh(interval=5000)  # 每5s自动刷新

# 定义列和数据
parameter_descriptions = {
    "cpu": [
        {"key": "%usr", "description": "用户空间占用CPU的百分比"},
        {"key": "%sys", "description": "内核空间占用CPU的百分比"},
        {"key": "%idle", "description": "CPU空闲时间百分比"},
        {"key": "%iowait", "description": "CPU等待I/O完成的时间百分比"},
        {"key": "%irq", "description": "处理硬件中断的时间百分比"},
        {"key": "%soft", "description": "处理软中断时间占比"},
        {"key": "%nice", "description": "nice值为负数的进程占比"},
        {"key": "load-1", "description": "近1分钟CPU平均负载"},
        {"key": "load-5", "description": "近5分钟CPU平均负载"},
        {"key": "load-15", "description": "近15分钟CPU平均负载"},
        {"key": "cs", "description": "上下文切换次数"}
    ],
    "disk": [
        {"key": "%drqm", "description": "磁盘读请求合并 (%)"},
        {"key": "%rrqm", "description": "磁盘读请求合并"},
        {"key": "%util", "description": "磁盘利用率 (%)"},
        {"key": "%wrqm", "description": "磁盘写请求合并"},
        {"key": "aqu-sz", "description": "平均队列大小"},
        {"key": "d/s", "description": "每秒磁盘操作数"},
        {"key": "d_await", "description": "平均等待时间 (ms)"},
        {"key": "dareq-sz", "description": "平均请求大小 (kB)"},
        {"key": "dkB/s", "description": "磁盘吞吐量 (kB/s)"},
        {"key": "drqm/s", "description": "每秒磁盘读请求合并"},
        {"key": "r/s", "description": "每秒读操作数"},
        {"key": "r_await", "description": "平均读等待时间 (ms)"},
        {"key": "rareq-sz", "description": "平均读请求大小 (kB)"},
        {"key": "rkB/s", "description": "读吞吐量 (kB/s)"},
        {"key": "rrqm/s", "description": "每秒磁盘读请求合并"},
        {"key": "w/s", "description": "每秒写操作数"},
        {"key": "w_await", "description": "平均写等待时间 (ms)"},
        {"key": "wareq-sz", "description": "平均写请求大小 (kB)"},
        {"key": "wkB/s", "description": "写吞吐量 (kB/s)"},
        {"key": "wrqm/s", "description": "每秒磁盘写请求合并"}
    ],
    "network": [
        {"key": "%ifutil", "description": "接口利用率 (%)"},
        {"key": "rxkB/s", "description": "接收吞吐量 (kB/s)"},
        {"key": "rxpck/s", "description": "每秒接收包数"},
        {"key": "txkB/s", "description": "发送吞吐量 (kB/s)"},
        {"key": "txpck/s", "description": "每秒发送包数"}
    ],
    "memory": [
        {"key": "%cache_buff", "description": "缓存和缓冲区内存 (%)"},
        {"key": "%free_memory", "description": "空闲内存 (%)"},
        {"key": "%free_swap", "description": "空闲交换区 (%)"}
    ]
}


# 数据库查询函数
def fetch_latest_data_from_db(db, device_name):
    return db.query(device_name, past_time=PastTime.NOW)


def fetch_past_data_from_db(db, device_name, past_time=PastTime.TEN_MIN):
    return db.query(device_name, past_time=past_time)


# 数据处理函数
def process_cpu_data(data):
    percentage_keys = ["%usr", "%sys", "%idle", "%iowait", "%irq", "%soft", "%nice"]
    value_keys = ["load-1", "load-5", "load-15", "cs"]
    return _process_data(data, percentage_keys, value_keys)


def process_cpu_data_past(data):
    percentage_keys = ["%usr", "%idle", "%iowait"]
    value_keys = []
    return _process_data(data, percentage_keys, value_keys)


def process_disk_data(data):
    percentage_keys = ["%drqm", "%util", "%rrqm", "%wrqm"]
    value_keys = ["aqu-sz", "d/s", "d_await", "dareq-sz", "dkB/s", "drqm/s", "r/s", "r_await", "rareq-sz", "rkB/s",
                  "rrqm/s", "w/s", "w_await", "wareq-sz", "wkB/s", "wrqm/s"]
    return _process_data(data, percentage_keys, value_keys)


def process_disk_data_past(data):
    percentage_keys = ["%util"]
    value_keys = ["r/s", "w/s", "r_await", "w_await"]
    return _process_data(data, percentage_keys, value_keys)


def process_network_data(data):
    percentage_keys = ["%ifutil"]
    value_keys = ["rxkB/s", "rxpck/s", "txkB/s", "txpck/s"]
    return _process_data(data, percentage_keys, value_keys)


def process_memory_data(data):
    percentage_keys = ["%cache_buff", "%free_memory", "%free_swap"]
    value_keys = []
    return _process_data(data, percentage_keys, value_keys)


def _process_data(data, percentage_keys, value_keys):
    percentage_data = {key: [d[key] for d in data if key in d] for key in percentage_keys}
    value_data = {key: [d[key] for d in data if key in d] for key in value_keys}
    return percentage_data, value_data


# 渲染图表的函数
def render_latest_chart(data_type, percentage_data, value_data):
    fig = go.Figure()

    # 添加百分比类型数据到图表
    for key, value in percentage_data.items():
        fig.add_trace(go.Bar(
            x=[key],
            y=[value[-1]] if value else [0],
            name=key,
            yaxis='y1',
            marker=dict(color='rgba(31, 119, 180, 0.8)')
        ))

    # 添加数值类型数据到图表
    for key, value in value_data.items():
        fig.add_trace(go.Bar(
            x=[key],
            y=[value[-1]] if value else [0],
            name=key,
            yaxis='y2',
            marker=dict(color='rgba(255, 127, 14, 0.8)')
        ))

    # 更新图表布局
    if data_type == 'cpu':
        fig.update_layout(
            title=f'{data_type.upper()} Current Metrics',
            xaxis=dict(title='Metrics'),
            yaxis=dict(
                title='Percentage',
                titlefont=dict(color='#1f77b4'),
                tickfont=dict(color='#1f77b4')
            ),
            yaxis2=dict(
                title='Value(log scale)',
                titlefont=dict(color='#ff7f0e'),
                tickfont=dict(color='#ff7f0e'),
                overlaying='y',
                side='right',
                type='log',
                dtick=1
            ),
            legend=dict(x=0, y=1.2, orientation='h'),
            barmode='group'
        )
    else:
        fig.update_layout(
            title=f'{data_type.upper()} Current Metrics',
            xaxis=dict(title='Metrics'),
            yaxis=dict(
                title='Percentage',
                titlefont=dict(color='#1f77b4'),
                tickfont=dict(color='#1f77b4')
            ),
            yaxis2=dict(
                title='Value',
                titlefont=dict(color='#ff7f0e'),
                tickfont=dict(color='#ff7f0e'),
                overlaying='y',
                side='right'
            ),
            legend=dict(x=0, y=1.2, orientation='h'),
            barmode='group'
        )

    st.plotly_chart(fig)


def render_past_chart(data_type, percentage_data, value_data):
    fig = go.Figure()

    # 获取当前时间，并生成过去十分钟内每个时间点
    now = datetime.datetime.now()
    # 总共需要120个点，每5秒一个点
    times = [now - datetime.timedelta(seconds=5 * i) for i in range(120)][::-1]

    # 添加百分比类型数据到图表
    for key, values in percentage_data.items():
        if len(values) > 120:  # 如果数据点多于120个，取最近的120个数据
            values = values[-120:]
        fig.add_trace(go.Scatter(
            x=times[:len(values)],  # 确保时间戳与数据点数匹配
            y=values,
            mode='lines',
            name=key,
            yaxis='y1',
            hoverinfo='x+y'
        ))

    # 添加数值类型数据到图表
    for key, values in value_data.items():
        if len(values) > 120:  # 如果数据点多于120个，取最近的120个数据
            values = values[-120:]
        fig.add_trace(go.Scatter(
            x=times[:len(values)],  # 确保时间戳与数据点数匹配
            y=values,
            mode='lines',
            name=key,
            yaxis='y2',
            hoverinfo='x+y'
        ))

    # 更新图表布局
    fig.update_layout(
        title=f'{data_type.upper()} Metrics Analysis (Last 10 minutes)',
        xaxis=dict(title='Time', type='date'),
        yaxis=dict(
            title='Percentage',
            titlefont=dict(color='#1f77b4'),
            tickfont=dict(color='#1f77b4')
        ),
        yaxis2=dict(
            title='Value',
            titlefont=dict(color='#ff7f0e'),
            tickfont=dict(color='#ff7f0e'),
            overlaying='y',
            side='right'
        ),
        legend=dict(x=0, y=1.2, orientation='h'),
        barmode='group'
    )

    st.plotly_chart(fig)


# 创建数据库实例
db = DataBase()

# 页面布局
st.title("Kylin-tune")
tab = st.sidebar.radio("选择页面", ["CPU", "Disk", "Memory", "Network"])

if tab == "CPU":
    st.header("CPU")

    # 获取最新数据
    latest_data = fetch_latest_data_from_db(db, DeviceName.CPU)
    percentage_data, value_data = process_cpu_data(latest_data)
    render_latest_chart('cpu', percentage_data, value_data)

    # 获取过去10分钟的数据
    past_data = fetch_past_data_from_db(db, DeviceName.CPU)
    percentage_data, value_data = process_cpu_data_past(past_data)
    render_past_chart('cpu', percentage_data, value_data)

    st.table(pd.DataFrame(parameter_descriptions['cpu']))

elif tab == "Disk":
    st.header("Disk")

    # 获取最新数据
    latest_data = fetch_latest_data_from_db(db, DeviceName.DISK)
    percentage_data, value_data = process_disk_data(latest_data)
    # st.write("Processed value data:", value_data['r/s'])  # 显示处理后的数值数据
    render_latest_chart('disk', percentage_data, value_data)

    # 获取过去10分钟的数据
    past_data = fetch_past_data_from_db(db, DeviceName.DISK)
    percentage_data, value_data = process_disk_data_past(past_data)
    # st.write("Processed value data:", value_data['r/s'])  # 显示处理后的数值数据
    render_past_chart('disk', percentage_data, value_data)

    st.table(pd.DataFrame(parameter_descriptions['disk']))

elif tab == "Memory":
    st.header("Memory")

    # 获取最新数据
    latest_data = fetch_latest_data_from_db(db, DeviceName.MEM)
    percentage_data, value_data = process_memory_data(latest_data)
    render_latest_chart('memory', percentage_data, value_data)

    # 获取过去10分钟的数据
    past_data = fetch_past_data_from_db(db, DeviceName.MEM)
    percentage_data, value_data = process_memory_data(past_data)
    render_past_chart('memory', percentage_data, value_data)

    st.table(pd.DataFrame(parameter_descriptions['memory']))

elif tab == "Network":
    st.header("Network")

    # 获取最新数据
    latest_data = fetch_latest_data_from_db(db, DeviceName.NET)
    percentage_data, value_data = process_network_data(latest_data)
    render_latest_chart('network', percentage_data, value_data)

    # 获取过去10分钟的数据
    past_data = fetch_past_data_from_db(db, DeviceName.NET)
    percentage_data, value_data = process_network_data(past_data)
    render_past_chart('network', percentage_data, value_data)

    st.table(pd.DataFrame(parameter_descriptions['network']))